package main

import (
	"context"
	"fmt"
	"github.com/coreos/etcd/clientv3"
	"log"
	"time"
)

func main() {
	cli, err := clientv3.New(clientv3.Config{
		Endpoints:   []string{"192.168.0.104:2379"},
		DialTimeout: 3 * time.Second,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer cli.Close()
	//上锁（创建租约，自动续租）
	lease := clientv3.NewLease(cli)
	//设置一个ctx取消自动续租
	ctx, cancleFunc := context.WithCancel(context.TODO())

	//设置10秒租约（过期时间）
	leaseResp, err := lease.Grant(context.TODO(), 10)
	if err != nil {
		fmt.Println(err)
		return
	}
	//拿到租约ID
	leaseId := leaseResp.ID
	//自动续租（不停往管道发送数据）
	leaseChan, err := lease.KeepAlive(ctx, leaseId)
	if err != nil {
		log.Fatal(err)
		return
	}
	//监听
	go linstenLeaseChan(leaseChan)
	//业务处理
	kv := clientv3.NewKV(cli)
	//创建事务
	txn := kv.Txn(context.TODO())
	txn.If(clientv3.Compare(clientv3.CreateRevision("/cron/lock/job9"), "=", 0)).
		Then(clientv3.OpPut("/cron/lock/job9", "xxx", clientv3.WithLease(leaseId))).
		Else(clientv3.OpGet("/cron/lock/job9")) //抢锁失败
		//提交事务
	txtResp, err := txn.Commit()
	if err != nil {
		fmt.Println(err)
		return
	} else {
		//判断是否抢锁
		if !txtResp.Succeeded {
			fmt.Println("锁被占用", string(txtResp.Responses[0].GetResponseRange().Kvs[0].Value))
			return
		}
	}
	for {
		time.Sleep(3 * time.Second)
		fmt.Println("休眠三秒")
	}
	//释放锁
	defer cancleFunc()                          //函数退出取消自动续租
	defer lease.Revoke(context.TODO(), leaseId) //终止租约（去掉过期时间）
	time.Sleep(10 * time.Second)

}
func linstenLeaseChan(leaseRespChan <-chan *clientv3.LeaseKeepAliveResponse) {
	var (
		leaseKeepResp *clientv3.LeaseKeepAliveResponse
	)
	for {
		select {
		case leaseKeepResp = <-leaseRespChan:
			if leaseKeepResp != nil {
				fmt.Println("租约失效了")
				goto END
			} else {
				fmt.Println("leaseKeepResp ID: ", leaseKeepResp.ID)

			}
		}
	END:
	}

}
